/**
 * http 请求
 */
import axios, { AxiosRequestConfig } from "axios";
import NProgress from "nprogress";

interface ResposeType<T> {
  code: number;
  data?: T;
  msg: string;
  err?: string;
}

interface Http {
  get<T>(url: string, params?: unknown): Promise<ResposeType<T>>;
  post<T>(url: string, params?: unknown): Promise<ResposeType<T>>;
  upload<T>(url: string, params: unknown): Promise<ResposeType<T>>;
  download(url: string): void;
}

type statusTypes =
  | 400
  | 401
  | 403
  | 404
  | 408
  | 500
  | 501
  | 502
  | 503
  | 504
  | 505;
const showStatus = (status: statusTypes): string => {
  let message = "";
  switch (status) {
    case 400:
      message = "请求错误(400)";
      break;
    case 401:
      message = "未授权，请重新登录(401)";
      break;
    case 403:
      message = "拒绝访问(403)";
      break;
    case 404:
      message = "请求出错(404)";
      break;
    case 408:
      message = "请求超时(408)";
      break;
    case 500:
      message = "服务器错误(500)";
      break;
    case 501:
      message = "服务未实现(501)";
      break;
    case 502:
      message = "网络错误(502)";
      break;
    case 503:
      message = "服务不可用(503)";
      break;
    case 504:
      message = "网络超时(504)";
      break;
    case 505:
      message = "HTTP版本不受支持(505)";
      break;
    default:
      message = `连接出错(${status})!`;
  }
  return `${message}，请检查网络或联系管理员！`;
};

let baseUrl = "/";

if (process.env.NODE_ENV === "production") {
  baseUrl = "localhost:5000";
} else if (process.env.NODE_ENV === "development") {
  baseUrl = "localhost:5000";
}
const service = axios.create({
  baseURL: baseUrl,
  headers: {
    get: {
      "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
    },
    post: {
      "Content-Type": "application/json;charset=utf-8"
    }
  } as any, // 暂时先这样处理
  withCredentials: false, // 是否跨站点访问控制请求, 是否携带 cookie
  timeout: 30000,
  // 请求数据转换
  transformRequest: [
    (data) => {
      return JSON.stringify(data);
    }
  ],
  // 响应数据转换
  transformResponse: [
    (data) => {
      if (typeof data === "string" && data.startsWith("{")) {
        data = JSON.parse(data);
      }
      return data;
    }
  ]
});

// 请求拦截器
service.interceptors.request.use(
  (config): AxiosRequestConfig<any> => {
    // const token = window.sessionStorage.getItem("token");
    // if (token) {
    //   config.headers!.token = token;
    // }
    // 让每个请求携带自定义 token
    config.headers && (config.headers["Authorization"] = "token");
    return config;
  },
  (error) => {
    // 错误抛到业务代码
    error.data = {};
    error.data.msg = "服务器异常，请联系管理员！";
    return Promise.resolve(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    if (response.data.code === "xxx") {
      // token过期操作
      window.sessionStorage.setItem("token", "");
      return response;
    }

    const status = response.status as statusTypes;
    let msg = "";
    if (status < 200 || status >= 300) {
      // 处理http错误，抛到业务代码
      msg = showStatus(status);
      if (typeof response.data === "string") {
        response.data = { msg };
      } else {
        response.data.msg = msg;
      }
      //拦截异常（通知）
      console.error({
        title: "提示",
        message: msg,
        type: "error"
      });
    }
    return response;
  },
  (error) => {
    // 错误抛到业务代码
    error.data = {};
    error.data.msg = "请求超时或服务器异常，请检查网络或联系管理员！";
    return Promise.resolve(error);
  }
);

const http: Http = {
  get(url, params) {
    return new Promise((resolve, reject) => {
      NProgress.start();
      service
        .get(url, { params })
        .then((res: { data: any }) => {
          NProgress.done();
          resolve(res.data);
        })
        .catch((err: { data: any }) => {
          NProgress.done();
          reject(err.data);
        });
    });
  },
  post(url, params) {
    return new Promise((resolve, reject) => {
      NProgress.start();
      service
        .post(url, JSON.stringify(params))
        .then((res: { data: any }) => {
          NProgress.done();
          resolve(res.data);
        })
        .catch((err: { data: any }) => {
          NProgress.done();
          reject(err.data);
        });
    });
  },
  upload(url, file) {
    return new Promise((resolve, reject) => {
      NProgress.start();
      service
        .post(url, file, {
          headers: { "Content-Type": "multipart/form-data" }
        })
        .then((res: { data: any }) => {
          NProgress.done();
          resolve(res.data);
        })
        .catch((err: { data: any }) => {
          NProgress.done();
          reject(err.data);
        });
    });
  },
  download(url) {
    const iframe = document.createElement("iframe");
    iframe.style.display = "none";
    iframe.src = url;
    iframe.onload = function () {
      document.body.removeChild(iframe);
    };
    document.body.appendChild(iframe);
  }
};

export default http;
